#!/usr/bin/python
# -*- encoding: utf-8 -*-
import re
import sys

FILEJSON = 'channels.json'
FILEXML = 'channels.xml'
HIDDEN = '_new'

def myChannels():
	try:
		import json
		import collections
		fd = open(FILEJSON)
		json_data = fd.read()
		channels = json.JSONDecoder(object_pairs_hook=collections.OrderedDict).decode(json_data)
		fd.close()
	except IOError:
		channels = {}

	return channels

#------------------------------------------------------------------------------------------------------------

def updateChannels(channels):
	try:

		channels[HIDDEN] = {}

		import json
		import urllib2
		import libxml2

		# Añadir nuevos
		oldTitles = {}
		oldLinks = []
		for cat, chns in channels.items():
			if not cat == HIDDEN:
				for chn, opts in chns.items():
					for opt in opts:
						oldLinks.append(opt)
						oldTitles[chn] = cat

		urls = {
			'http://dl.dropboxusercontent.com/u/47839851/canales%20XBMC.xml': [],
			'http://dl.dropboxusercontent.com/u/4735170/streams.xml'        : [['>\tlink>'                     , '><link>'                            ]],
			'http://dl.dropboxusercontent.com/u/202352798/Lista.xml'        : [['<title>Actualizado 18/09/2013', '<item><title>Actualizado 18/09/2013']],
		}

		new = []
		for url, replaces in urls.iteritems():
			resp = urllib2.urlopen(url)

			if resp.getcode() == 200:
				xml = resp.read()
				xml = re.sub('&'     , '&amp;', xml)
				xml = re.sub(r'\r|\n', ''     , xml)

				for replace in replaces:
					xml = re.sub(replace[0], replace[1], xml)

				xml = libxml2.parseDoc(xml)

				for categoryNode in xml.xpathEval('//channel|//subchannel'):
					for chnNode in categoryNode.xpathEval('.//item|.//subitem'):
						title = unicode(chnNode.xpathEval('title')[0].content, 'utf-8')
						link =  unicode(chnNode.xpathEval('link' )[0].content, 'utf-8')
						if link.endswith('"'):
							link = link[:-1]

						if not re.match('(\(OFF\))', title) and re.match('.+://.+', link) and not link in oldLinks:
							category = HIDDEN
							for oldTitle, oldCategory in oldTitles.items():
								if title.lower().replace(' ', '') == oldTitle.lower().replace(' ', ''):
									category = oldCategory
									title = oldTitle
							if title in channels[category]:
								if not link in channels[category][title]:
									channels[category][title].append(link)
							else:
								channels[category][title] = [link]
						new.append(link)

			resp.close()

		# Eliminar viejos
		for cat, chns in channels.items():
			for chn, opts in chns.items():
				for opt in opts:
					if not opt in new:
						channels[cat][chn].remove(opt)
				if len(channels[cat][chn]) == 0:
					channels[cat].pop(chn, None)

		printJSON(channels)
		channels.pop(HIDDEN, None)

	except Exception as ex:
		import traceback
		print traceback.print_exc()

	return channels

#------------------------------------------------------------------------------------------------------------

def printJSON(channels):
	import cgi
	tabs=17
	first = [True, True]

	out = '{'
	for cat, chns in channels.items():
		out += (',' if not first[0] else '') + '\n\t"' + cat + '": {'
		first[1] = True
		for chn, opts in chns.items():
			out += (',' if not first[1] else '') + '\n\t\t"' + chn + '":' + ('\t' * (tabs - 2 - (len(chn)+3)/4))
			out += '["' + ('",\n' + ('\t' * tabs) + '"').join(opts) + '"]'
			first[1] = False
		out += '\n\t}'
		first[0] = False
	out += '\n}'
	print >>open(FILEJSON, 'w'), out.encode('utf-8')

#------------------------------------------------------------------------------------------------------------

def printXML(channels):
	import cgi
	out = '<?xml version="1.0" encoding="UTF-8" standalone="no"?><channels>'
	for cat, chns in channels.items():
		out += '\n<channel><name>' + cat.encode('ascii', 'xmlcharrefreplace') + '</name><thumbnail>none</thumbnail>'
		for chn, opts in chns.items():
			chn = chn.encode('ascii', 'xmlcharrefreplace')
			i = 1
			for opt in opts:
				opt = opt.encode('ascii', 'xmlcharrefreplace')
				out += '\n\t<item><title>' + chn + (' (op ' + str(i) + ')' if len(opts)>1 else '') + '</title><link>' + opt + '</link></item>'
				i+=1
		out += '</channel>'
	out += '</channels>'
	print >>open(FILEXML, 'w'), out

#------------------------------------------------------------------------------------------------------------

class AutoComplete(object):
	def __init__(self, options):
		self.options = options

	def complete(self, text, state):
		if state == 0:  # on first trigger, build possible matches
			if text:  # cache matches (entries that start with entered text)
				self.matches = [s for s in self.options 
									if s and s.startswith(text)]
			else:  # no text entered, all matches possible
				self.matches = self.json[:]

		# return match indexed by state
		try: 
			return self.matches[state]
		except IndexError:
			return None

#------------------------------------------------------------------------------------------------------------

if 	not '-u' in sys.argv and not '-p' in sys.argv and not '-m' in sys.argv:
	print 'usage ' + sys.argv[0] + ' -m (Display Menu) -u (Update channels) -p (print XML)'

else:
	channels = myChannels()
	if '-u' in sys.argv:
		channels = updateChannels(channels)

	if '-p' in sys.argv:
		printXML(channels)

	if '-m' in sys.argv:
		import os
		import readline

		completer = AutoComplete([])
		readline.set_completer(completer.complete)
		readline.parse_and_bind('tab: complete')

		subss = {
			'(?i)live=1'   : [' -v ' ,  ''],
			'(?i)playpath=': [' -y "', '"'],
			'(?i)swfUrl='  : [' -W "', '"'],
			'(?i)pageUrl=' : [' -p "', '"'],
			'(?i)conn='    : [' -C "', '"'],
			'(?i)token='   : [' -T "', '"']
		}
		while True:
			os.system('clear')
			print '\n'.join(channels)
			completer.options = sorted(channels)
			cat = raw_input('> ')
			if cat in channels:
				chns = channels[cat]
				os.system('clear')
				print '\n'.join(chns)
				completer.options = sorted(chns)
				chn = raw_input(cat + '> ')
				if chn in chns:
					status = 0
					for opt in chns[chn]:
						if status == 0:
							if re.match('rtmpe?\:\/\/.*', opt):
								parts = opt.split(' ')
								for i in range(len(parts)):
									for sub, subs in subss.items():
										if re.match(sub, parts[i]):
											parts[i] = re.sub(sub, subs[0], parts[i]) + subs[1]
								opt = 'rtmpdump -r ' + ' '.join(parts) + ' | mplayer -cache 8192 -'
							elif re.match('http\:\/\/.*\.m3u8', opt):
								opt = 'mplayer -user-agent "Apple-iPhone3C1/801.293" ' + opt
							else:
								opt = 'mplayer ' + opt
							os.system('clear')
							print cat + '/' + chn + '> ' + opt
							status = os.system(opt)
					raw_input('Pulsa "enter" para continuar')
